import Taro from '@tarojs/taro'

// 错误码映射
const ERROR_CODE_MAP = {
  400: '请求参数错误',
  401: '未授权，请重新登录',
  403: '拒绝访问',
  404: '请求地址不存在',
  408: '请求超时',
  500: '服务器内部错误',
  502: '网关错误',
  503: '服务不可用',
  504: '网关超时'
}

// 业务错误码映射
const BUSINESS_ERROR_MAP = {
  1001: '用户未登录',
  1002: '用户信息已过期',
  1003: '权限不足',
  2001: '订单不存在',
  2002: '订单状态异常',
  3001: '余额不足',
  3002: '优惠券不可用'
}

// 请求基础配置
const baseConfig = {
  baseURL: process.env.NODE_ENV === 'development' ? '' : 'https://api.example.com',
  timeout: 10000,
  header: {
    'Content-Type': 'application/json'
  }
}

// 统一错误处理
const handleError = (error, url, method) => {
  console.error(`请求错误 [${method} ${url}]:`, error)
  
  let errorMessage = '请求失败'
  
  if (error.statusCode) {
    // HTTP 状态码错误
    errorMessage = ERROR_CODE_MAP[error.statusCode] || `HTTP错误: ${error.statusCode}`
  } else if (error.code) {
    // 业务错误码
    errorMessage = BUSINESS_ERROR_MAP[error.code] || error.message || '业务处理失败'
  } else if (error.errMsg) {
    // 微信小程序错误
    if (error.errMsg.includes('timeout')) {
      errorMessage = '请求超时，请检查网络连接'
    } else if (error.errMsg.includes('fail')) {
      errorMessage = '网络连接失败，请检查网络'
    } else {
      errorMessage = error.errMsg
    }
  } else if (error.message) {
    errorMessage = error.message
  }

  // 特殊错误处理
  if (error.statusCode === 401 || error.code === 1001 || error.code === 1002) {
    // 登录过期，清除本地数据并跳转登录
    Taro.removeStorageSync('token')
    Taro.removeStorageSync('userInfo')
    
    setTimeout(() => {
      Taro.navigateTo({ url: '/pages/login/index' })
    }, 1500)
    
    errorMessage = '登录已过期，请重新登录'
  }

  // 显示错误提示
  Taro.showToast({
    title: errorMessage,
    icon: 'none',
    duration: 2000
  })

  return Promise.reject(new Error(errorMessage))
}

// 请求拦截器
const interceptor = function (chain) {
  const requestParams = chain.requestParams
  const { method, data, url } = requestParams

  // 开发环境打印请求日志
  if (process.env.NODE_ENV === 'development') {
    console.log(`🚀 HTTP ${method || 'GET'} --> ${url}`)
    if (data && Object.keys(data).length > 0) {
      console.log('📤 请求参数：', data)
    }
  }

  // 添加认证头
  const token = Taro.getStorageSync('token')
  if (token) {
    requestParams.header = {
      ...requestParams.header,
      'Authorization': `Bearer ${token}`
    }
  }

  // 添加设备信息
  const systemInfo = Taro.getSystemInfoSync()
  requestParams.header = {
    ...requestParams.header,
    'X-Device-Type': systemInfo.platform,
    'X-App-Version': '1.0.0'
  }

  return chain.proceed(requestParams)
    .then(res => {
      // 开发环境打印响应日志
      if (process.env.NODE_ENV === 'development') {
        console.log(`📥 HTTP ${method || 'GET'} <-- ${url} [${res.statusCode}]`)
        console.log('📦 响应数据：', res.data)
      }

      // 统一处理响应
      if (res.statusCode >= 200 && res.statusCode < 300) {
        // 处理不同的响应格式
        if (res.data && typeof res.data === 'object') {
          const { code, message, data: responseData, msg } = res.data
          
          // 标准格式：{ code, message, data }
          if (code !== undefined) {
            if (code === 200 || code === 0) {
              return responseData || res.data
            } else {
              return handleError({ code, message: message || msg }, url, method)
            }
          }
          
          // 直接返回数据
          return res.data
        }
        
        return res.data
      } else {
        // HTTP 状态码错误
        return handleError({ statusCode: res.statusCode }, url, method)
      }
    })
    .catch(err => {
      // 网络错误或其他异常
      return handleError(err, url, method)
    })
}

// 添加拦截器
Taro.addInterceptor(interceptor)

// 请求队列管理
class RequestQueue {
  constructor() {
    this.queue = new Map()
    this.maxRetry = 3
  }

  // 生成请求key
  generateKey(url, method, data) {
    return `${method}_${url}_${JSON.stringify(data || {})}`
  }

  // 添加请求到队列
  add(url, method, data, options = {}) {
    const key = this.generateKey(url, method, data)
    
    // 防止重复请求
    if (this.queue.has(key) && !options.allowDuplicate) {
      console.warn('重复请求被拦截:', key)
      return this.queue.get(key)
    }

    const requestPromise = this.executeRequest(url, method, data, options)
    this.queue.set(key, requestPromise)

    // 请求完成后从队列中移除
    requestPromise.finally(() => {
      this.queue.delete(key)
    })

    return requestPromise
  }

  // 执行请求
  async executeRequest(url, method, data, options, retryCount = 0) {
    try {
      const requestConfig = {
        url: baseConfig.baseURL + url,
        method: method.toUpperCase(),
        data,
        header: { ...baseConfig.header, ...options.header },
        timeout: options.timeout || baseConfig.timeout
      }

      return await Taro.request(requestConfig)
    } catch (error) {
      // 重试机制
      if (retryCount < this.maxRetry && this.shouldRetry(error)) {
        console.log(`请求重试 ${retryCount + 1}/${this.maxRetry}:`, url)
        await this.delay(1000 * (retryCount + 1)) // 递增延迟
        return this.executeRequest(url, method, data, options, retryCount + 1)
      }
      throw error
    }
  }

  // 判断是否应该重试
  shouldRetry(error) {
    // 网络错误或超时错误可以重试
    return error.errMsg && (
      error.errMsg.includes('timeout') ||
      error.errMsg.includes('fail') ||
      error.errMsg.includes('network')
    )
  }

  // 延迟函数
  delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms))
  }

  // 清空队列
  clear() {
    this.queue.clear()
  }
}

// 创建请求队列实例
const requestQueue = new RequestQueue()

// 封装请求方法
const request = {
  // GET 请求
  get(url, params = {}, options = {}) {
    return requestQueue.add(url, 'GET', params, options)
  },

  // POST 请求
  post(url, data = {}, options = {}) {
    return requestQueue.add(url, 'POST', data, { ...options, allowDuplicate: true })
  },

  // PUT 请求
  put(url, data = {}, options = {}) {
    return requestQueue.add(url, 'PUT', data, { ...options, allowDuplicate: true })
  },

  // DELETE 请求
  delete(url, params = {}, options = {}) {
    return requestQueue.add(url, 'DELETE', params, options)
  },

  // PATCH 请求
  patch(url, data = {}, options = {}) {
    return requestQueue.add(url, 'PATCH', data, { ...options, allowDuplicate: true })
  },

  // 上传文件
  upload(url, filePath, formData = {}, options = {}) {
    const token = Taro.getStorageSync('token')
    
    return Taro.uploadFile({
      url: baseConfig.baseURL + url,
      filePath,
      name: options.name || 'file',
      formData,
      header: {
        'Authorization': token ? `Bearer ${token}` : '',
        ...options.header
      }
    }).then(res => {
      if (res.statusCode === 200) {
        try {
          const data = JSON.parse(res.data)
          if (data.code === 200) {
            return data.data
          } else {
            throw new Error(data.message || '上传失败')
          }
        } catch (e) {
          throw new Error('响应数据格式错误')
        }
      } else {
        throw new Error('上传失败')
      }
    }).catch(err => {
      return handleError(err, url, 'UPLOAD')
    })
  },

  // 下载文件
  download(url, options = {}) {
    const token = Taro.getStorageSync('token')
    
    return Taro.downloadFile({
      url: baseConfig.baseURL + url,
      header: {
        'Authorization': token ? `Bearer ${token}` : '',
        ...options.header
      }
    }).catch(err => {
      return handleError(err, url, 'DOWNLOAD')
    })
  },

  // 清空请求队列
  clearQueue() {
    requestQueue.clear()
  },

  // 设置基础URL
  setBaseURL(url) {
    baseConfig.baseURL = url
  },

  // 设置默认头部
  setDefaultHeader(header) {
    baseConfig.header = { ...baseConfig.header, ...header }
  }
}

export default request
